// 网络请求状态基类
abstract class NetworkState<T> {
  const NetworkState();

  R when<R>({
    required R Function() initial,
    required R Function() loading,
    required R Function(T data) success,
    required R Function(String error, int? statusCode) failure,
  }) {
    if (this is NetworkInitial<T>) {
      return initial();
    } else if (this is NetworkLoading<T>) {
      return loading();
    } else if (this is NetworkSuccess<T>) {
      return success((this as NetworkSuccess<T>).data);
    } else if (this is NetworkFailure<T>) {
      return failure(
        (this as NetworkFailure<T>).error,
        (this as NetworkFailure<T>).statusCode,
      );
    }
    throw Exception('Unknown NetworkState type');
  }
}

// 初始状态
class NetworkInitial<T> extends NetworkState<T> {
  const NetworkInitial();
}

// 加载中状态
class NetworkLoading<T> extends NetworkState<T> {
  const NetworkLoading();
}

// 成功状态
class NetworkSuccess<T> extends NetworkState<T> {
  final T data;

  const NetworkSuccess(this.data);

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    return other is NetworkSuccess<T> && other.data == data;
  }

  @override
  int get hashCode => data.hashCode;
}

// 失败状态
class NetworkFailure<T> extends NetworkState<T> {
  final String error;
  final int? statusCode;

  const NetworkFailure(this.error, {this.statusCode});

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    return other is NetworkFailure<T> &&
        other.error == error &&
        other.statusCode == statusCode;
  }

  @override
  int get hashCode => Object.hash(error, statusCode);
}

// 扩展方法，方便使用
extension NetworkStateExtensions<T> on NetworkState<T> {
  bool get isInitial => this is NetworkInitial<T>;
  bool get isLoading => this is NetworkLoading<T>;
  bool get isSuccess => this is NetworkSuccess<T>;
  bool get isFailure => this is NetworkFailure<T>;

  T? get dataOrNull => isSuccess ? (this as NetworkSuccess<T>).data : null;
  String? get errorOrNull =>
      isFailure ? (this as NetworkFailure<T>).error : null;
}
